import json
import os
import re
import time

import requests
from lxml import etree

from tools import *

r = redis.Redis(host='localhost', port=6379, db=0)


def get_product_details(id_):
    """获取商品详情页"""
    url = f"https://www.smzdm.com/p/{id_}/"
    response =ownRequest(method="GET", url=url)
    return response.content.decode()


def get_category_value(div):
    """从商品链接中提取类别信息"""
    onclick_attr = div.xpath('//img[@class="main-img"]/@onclick')[0]
    category_match = re.search(r"'category':'([^']*)'", onclick_attr)
    if category_match:
        return category_match.group(1)
    return None


def get_brands(htms_str):
    """提取品牌信息"""
    pattern1 = r"'brand'\s*:\s*'([^']+)'"
    pattern2 = r"'ecommerce'\s*:\s*{[^}]*'products'\s*:\s*\[{[^}]*'brand'\s*:\s*'([^']+)'"
    brands = re.findall(pattern1, htms_str) + re.findall(pattern2, htms_str)
    return "".join(list(set(brands)))  # 去重后输出


def get_time_string(time_string):
    """处理时间格式"""
    now = datetime.datetime.now()
    if re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}', time_string):
        return time_string
    elif re.match(r'^\d{2}-\d{2} \d{2}:\d{2}', time_string):
        return f"{now.year}-{time_string}"
    elif re.match(r'^\d{2}:\d{2}$', time_string):
        return f"{now.strftime('%Y-%m-%d')} {time_string}"
    return None



def upload_cookie(cookie_str):
    # 上传cookie
    ownRequest2("http://test-node.lottefuture.com/smzdm/cookie",method="POST", data=cookie_str, headers={
        'Content-Type': 'text/plain',
        'Host': 'test-node.lottefuture.com'
    })
    return

def fetch_shop_info(shop_buy_url):
    """获取商品信息"""

    if not shop_buy_url:return  None

    link_url = shop_buy_url.replace("https://", "")

    shop_url = f"http://test-node.lottefuture.com/smzdm/?url=https://{link_url}"

    # 解析数据
    response = ownRequest2(shop_url,"GET",timeout=3)

    # 获取restoredLink
    data_json = response.json()
    # 解析restoredLink
    try:
        restoredLink = data_json.get("data").get("restoredLink")
        # 获取商品信息

        shop_detail = get_shop_parse(restoredLink)

        product_msg_all = shop_detail.get("data").get("items")

        return product_msg_all
    except:
        return None
    # return shop_link_response.json() if shop_link_response.status_code == 200 else None


def fetch_coupons(all_result, div):
    """获取优惠券信息"""
    coupons = []
    parent_paths = [
        "/html/body/div[1]/div/section[1]/article/div[1]/div[2]/div/div[2]/div[3]/div[2]/div[2]",
        "/html/body/div[1]/div/section[1]/article/div[1]/div[2]/div/div[2]/div[2]/div[2]/div[2]",
        "/html/body/div[1]/div/section[1]/article/div[1]/div[2]/div/div[2]/div[3]/div[4]/div[2]",
        "/html/body/div[1]/div/section[1]/article/div[1]/div[2]/div/div[2]/div[2]/div[4]/div[2]"
    ]

    for path in parent_paths:
        parent_elements = all_result.xpath(path)
        if not parent_elements:
            continue
        parent = parent_elements[0]
        children = parent.xpath("./*")

        for child in children:
            if child.tag == "a":
                data_dimension122 = child.xpath('./@data-dimension122')[0]
                tag_text = child.xpath('./span/text()')[0]
                you_hui_tiao_zhuan_link = child.xpath('./@href')[0] if child.xpath('./@href') else None

                temp  =  fetch_shop_info(you_hui_tiao_zhuan_link)

                try:
                    platform = temp[0]['matchedPlatforms'][0]['platformName']
                    url = temp[0]['matchedText']
                except:
                    # 解析失败 返回原链接
                    platform = None
                    url = you_hui_tiao_zhuan_link
                coupons.append({
                    "data-dimension122": data_dimension122,
                    "tag_text": tag_text,
                    "you_hui_tiao_zhuan_link_end": url,
                    "huo_dong_time" : None, # 默认没有活动时间:
                    "platform" : platform
                })
    return coupons





def process_data_for_redis(coupons, id_, category_value, smdzdm_san_ji_category, title, smzdm_brand_name, price, update_time, buy_platform,
                           order_num, pay_amount, start_shop_buy, shop_buy_url, bao_liao_msg, product_id, platform_name,
                           comment_img,ai_text):
    """将数据整理并存入Redis"""
    end_list_fang_an_buy = []
    seen_links = set()
    for coupon in coupons:
        if "礼金" in coupon.get('tag_text') or "值得买" in coupon.get('tag_text'):
            continue
        if coupon.get('tag_text') not in seen_links:
            end_list_fang_an_buy.append(coupon)
            seen_links.add(coupon.get('tag_text'))



    data = {
        "id": id_,
        "smdzdm_category_value": category_value,
        "smdzdm_san_ji_category": smdzdm_san_ji_category,
        "smdzdm_brand_name": smzdm_brand_name,
        "title": title,
        "price": price,
        "update_time": update_time,
        "buy_platform": buy_platform,
        "buy_fang_an": end_list_fang_an_buy,
        "order_num": order_num,
        "pay_amount": pay_amount,
        "start_shop_buy": start_shop_buy,
        "shop_buy_url": shop_buy_url,
        "bao_liao_title": bao_liao_msg,
        "product_id": product_id,
        "platform_name": platform_name,
        "comment_img": comment_img,
        "ai_text":ai_text


    }

    req = requests.post(REMOTE_DB_PUSH_URL, json=data, verify=False)

    if "success" not in req.content.decode():
        print("推送请求失败: ",data['id'])
        return False
    else:
        print(f"推送成功:\n      ID = {data['id']} 完成采集,{str(data)[:100]}...")
        return True

    # 将数据写入Redis队列
    # redis_conn.rpush("smdzdm_product_message_queue", json.dumps(data, ensure_ascii=False))
    # print(f"id: {data['id']} 已经完成采集")

def get_shop_parse(shop_url_other):
    # 获取商品ID,通过解析接口
    jie_xi_url = "http://cgi-bin.lottefuture.com/python/link-parse.php"
    json1 = {
        "content": shop_url_other,
    }

    # 经常时间超时 重试后又可以通过 尝试延长时间
    for i in range(5):
        try:
            shop_post_link_response = ownRequest2(jie_xi_url,method="POST" ,json=json1, timeout=3)
            break
        except Exception as e:
            print("异常信息=>",e)
            continue
    end_shop_detail_result = shop_post_link_response.json()
    return end_shop_detail_result

def to_map(new_name,own_name,table):

    """
    建立品牌和品类的映射关系，并记录 title，用于辅助判断分类准确性。
    """

    """
     插入或合并 original_name 数据记录。

     参数:
     conn: sqlite3.Connection 数据库连接
     new_record: dict，包含字段 original_name, standard_name, flag
     """
    if new_name in ["其它品牌","其它","其他家","其他品牌","其他","未知",""]:
        own_name="未知"






    temp = f"SELECT standard_name FROM {table} WHERE original_name = %s"
    cursor.execute(temp, (new_name,))

    row = cursor.fetchone()

    if row is None:
        # 如果不存在，则插入新行，flag默认为0
        temp = f"""
            INSERT INTO {table} (original_name, standard_name, multiple_flag)
            VALUES (%s, %s, 0)
        """

        cursor.execute(temp, (new_name, own_name))

    else:

        # 如果表中已经有该品牌的映射 则不进行任何操作
        return


        # 如果存在，则拼接 standard_name，并更新 flag 为 1
        existing_standard_name = row[0]
        lis = existing_standard_name.split('||')
        if own_name not in lis:  # 避免重复拼接
            new_standard_name = f"{existing_standard_name}||{own_name}"
            flag = 1
        else:
            new_standard_name = existing_standard_name
            flag = 0 if len(lis) <=1 else 1
        temp = f"""
            UPDATE {table}
            SET standard_name = %s, multiple_flag = %s
            WHERE original_name = %s
        """
        cursor.execute(temp, (new_standard_name,flag, new_name))

    conn.commit()

            # brand_mapping.setdefault(new_brand, set()).add(own_brand)
def extract_brand_and_category(item, platform):
    try:
        if platform == '淘宝':
            item = item['result_list'][0]
            return {
                'brand_name': item['item_basic_info'].get('brand_name'),
                'category_name': item['item_basic_info'].get('category_name'),
                'title': item['item_basic_info'].get('title')
            }
        elif platform == '京东':
            item = item['data'][0]
            return {
                'brand_name': item.get('brandName'),
                'category_name': "、".join([
                    item['categoryInfo'].get('cid1Name', ''),
                    item['categoryInfo'].get('cid2Name', ''),
                    item['categoryInfo'].get('cid3Name', '')
                ]),
                'title': item.get('skuName')
            }
        elif platform == '拼多多':
            item = item['goods_details'][0]
            cat_ids = item['cat_ids']
            category_lis = []


            for _ in cat_ids:

                res_json = requests.get(f"http://cgi-bin.lottefuture.com/python/pdd-goods-cat-get.php?cat_id={_}").json()
                if res_json.get("status") != "200":
                    print("拼多多 类目ID查询失败,类目id => ",_)
                    return  None

                category_lis.append(res_json.get("data").get("category_name"))
            return  {
                'brand_name': item.get('brand_name'),
                'category_name': "\\".join(category_lis),
                'title': item.get('goods_name')}
        elif platform == '唯品会':
            item = item['result'][0]
            return  {
                'brand_name': item.get('brandName'),
                'category_name': "\\".join([item.get("cat1stName",""),item.get("cat2ndName",""),item.get("categoryName","")]), # TODO
                'title': item.get('goodsName')
            }
        # 其它平台解析
        else:
            return None
    except Exception as e:
        # 失败
        return None
def fetch_platform_data(itemId, key):
    params = {'itemId': itemId}
    try:
        response = requests.get(url_map[key], params=params, timeout=5,verify=False, proxies=PROXIES, headers={"Connection": "Close"})
        response.raise_for_status()
        return response.json()
    except Exception as e:
        # 请求失败
        return None


def load_state():
    """加载模型调用状态"""
    if os.path.exists(STATE_FILE):
        with open(STATE_FILE, "r", encoding="utf-8") as f:
            return json.load(f)
    else:
        return {
            "current_index": 0,
            "usage_counts": {model: 0 for model in MODEL_LIST}
        }


def save_state(state):
    """保存模型调用状态"""
    with open(STATE_FILE, "w", encoding="utf-8") as f:
        json.dump(state, f, indent=2)


def get_next_model():
    """返回当前可用模型，记录一次调用，必要时切换到下一个模型"""
    state = load_state()
    idx = state["current_index"]
    usage = state["usage_counts"]

    while idx < len(MODEL_LIST):
        model = MODEL_LIST[idx]
        if usage[model] < MAX_CALLS_PER_MODEL:
            usage[model] += 1
            break
        else:
            idx += 1  # 当前模型已达上限，尝试下一个模型

    if idx >= len(MODEL_LIST):
        raise Exception("所有模型调用次数都已达上限！")

    # 更新状态并保存
    state["current_index"] = idx
    state["usage_counts"] = usage
    save_state(state)
    return model
def GPT_promote(text):

    completion = client.chat.completions.create(
        # 模型列表：https://help.aliyun.com/zh/model-studio/getting-started/models
        model=f"{get_next_model()}",
        messages=[
            {"role": "system",
             "content": "请根据用户发送给你的原始文案，重构为自然流畅的推广文案，不需要添加说明或废话，仅输出一段文字。"},
            {"role": "user",
             "content": f"{text}"},
        ],

        extra_body={"enable_thinking": False}
        # Qwen3模型通过enable_thinking参数控制思考过程（开源版默认True，商业版默认False）
        # 使用Qwen3开源版模型时，若未启用流式输出，请将下行取消注释，否则会报错
        # extra_body={"enable_thinking": False},
    )

    return completion.choices[0].message.content


def process_imgUrl(img_url):
    url  ="http://xdrj.lottefuture.com/zxy/V1/Gen2/ed1XF/ModuleController/SearchModule/uploadImg"

    files = [
        ('Img', (f'{int(time.time())}.png', requests.get(img_url).content,
                 'image/webp'))
    ]

    res = ownRequest2(url,method="POST",timeout=3,files=files)

    try:
        return res.json().get("data", None)
    except:
        print(f"上传图片{img_url}失败,返回的响应=> {res.text if res else  None}")
        return None

def get_zdm_detail():
    while True:
        # 只获取第一页的商品信息
        ids = get_product_list()

        for id_ in ids:
            try:
                if r.sismember("unique_set_smzdm", id_):
                    print("此商品ID已经提取过: ", id_)
                    continue
                time.sleep(3)
                htms_str = get_product_details(id_)
                all_result = etree.HTML(htms_str)

                try:
                    div = all_result.xpath("//div[@class='info J_info']/a[@class='img-box']")[0]
                except:
                    continue

                category_value = get_category_value(div)
                smdzdm_san_ji_category = '/'.join(category_value.split('/', 3)[:3]) if category_value else None
                title = "".join(div.xpath("//h1[@class='title J_title']/text()")).strip()
                price = "".join(div.xpath("//span[@class='price-large']//text()")).strip()
                update_time = get_time_string("".join(div.xpath("//span[@class='time']//text()")).replace("\n", "").replace("更新时间：",
                                                                                                            "").strip())
                buy_platform = "".join(
                    div.xpath("//div[@class='canal']//div[@class='item-subtitle']/span[1]/text()")).strip()

                if buy_platform == "京东国际":
                    buy_platform = "京东"
                elif buy_platform in ["天猫精选", "天猫超市", "天猫国际", "淘宝精选"]:
                    buy_platform = "淘宝"

                order_num = "".join(div.xpath("//div[@class='number']//span/text()")).strip()
                pay_amount = "".join(div.xpath("//div[@class='money']//span/text()")).strip()
                start_shop_buy = "".join(div.xpath("//div[@class='more-day']//span//text()")).strip()
                shop_buy_url = "".join(div.xpath("//a[@class='go-buy btn']/@href[1]")).strip()

                # 爆料信息
                bao_liao_title = "".join(
                    div.xpath("//div[@class='baoliao-block']//div[@class='name one-line']/text()")).strip()
                bao_liao_content = "".join(div.xpath("//div[@class='baoliao-block']/p[1]//text()")).strip()
                bao_liao_content1 = "".join(div.xpath("//div[@class='baoliao-block']/p[2]//text()")).strip()
                bao_liao_msg = f"{bao_liao_title}{bao_liao_content}{bao_liao_content1}"

                if not shop_buy_url:
                    print(f"{id_}--没有购买链接--跳过")
                    continue

                # TODO

                cookies_str = '; '.join([f"{cookie.name}={cookie.value}" for cookie in session.cookies])

                upload_cookie(cookies_str)

                # 获取商品ID
                product_msg_all = fetch_shop_info(shop_buy_url)

                if not product_msg_all:
                    print(f"解析链接时产生数据响应错误----")
                    continue

                product_id = None
                platform_name = None
                for product in product_msg_all:
                    for msg in product.get("matchedPlatforms"):
                        platform_name = msg.get("platformName")
                        if not msg.get("data"): continue
                        product_id = msg.get("data").get("productInfo").get("productId")
                        break


                if not  product_id:continue
                # comment_img = div.xpath("//div[@class='order-img preview-img']/img/@src")

                comment_img = [process_imgUrl(img_url.strip().replace("_a200.jpg","")) for img_url in div.xpath("//div[@class='order-img preview-img']/img/@src")]

                # 获取优惠券
                coupons = fetch_coupons(all_result, div)


                """
                smdzdm_category_value
                smdzdm_brand_name
                platform_name  buy_platform
                product_id
                """

                result = None
                smzdm_brand_name = get_brands(htms_str)

                # 若支持该平台  则创建映射
                if buy_platform  in PLATFORM_LIS and product_id:
                    platform_data = fetch_platform_data(product_id, buy_platform)
                    if platform_data:
                        result = extract_brand_and_category(platform_data, platform_name)
                    if result:
                        new_brand, new_category, title = result.values()
                        to_map(new_brand, smzdm_brand_name, "brand_mapping")
                        to_map(new_category, category_value, "category_mapping")

                # 过滤功能
                try:
                    ai_text = GPT_promote(bao_liao_msg)
                except:
                    print(f"id:{id_} 调用GPT接口失败=> \n\n")
                    traceback.print_exc()
                    continue


                # TODO 远程推送  将数据存入Redis
                statu = process_data_for_redis(coupons, id_, category_value, smdzdm_san_ji_category, title,smzdm_brand_name, price, update_time,
                                       buy_platform, order_num, pay_amount, start_shop_buy, shop_buy_url, bao_liao_msg,
                                       product_id, platform_name, comment_img,ai_text)
                if statu:
                    r.sadd("unique_set_smzdm", id_)
            except Exception as e:
                print(f"处理id{id_}时, 发生异常=> \n")
                traceback.print_exc()
                continue
        time.sleep(20)

if __name__ == '__main__':
    get_zdm_detail()

    # res = process_imgUrl("https://y.zdmimg.com/202505/27/68359d7cf67c97004.jpg")
    # print(res)
    # print(res)
